package com.ruan.filter;

import cn.hutool.json.JSONObject;
import com.ruan.openfeign.AdminCenterOpenfeign;
import com.ruan.openfeign.UserCenterOpenfeign;
import com.ruan.utils.Auth0JwtUtils;
import com.ruan.utils.LongAuth0JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * @ClassName:MyLogGateWayFilter
 * @Author:阮昇
 * @Description:
 * @Datetime: 2023/6/29 10:03
 **/
@Component
public class MyLogGateWayFilter implements GlobalFilter, Ordered {
    @Lazy
    @Autowired
    private UserCenterOpenfeign userCenterOpenfeign;

    @Lazy
    @Autowired
    private AdminCenterOpenfeign adminCenterOpenfeign;

    private final List<String> whiteList = Arrays.asList("/user/userlogin","/user/register","/verifyCode/getVerifyCode","/goods/uploadGoodsPicture","/admin/adminlogin","/user/uploadAvatar","/comments/uploadCommentsPicture"); // 白名单中的路径


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String url = exchange.getRequest().getPath().toString();
        if (isWhiteList(url)) { // 判断请求路径是否在白名单中
            return chain.filter(exchange); // 在白名单中，则直接放行
        }
        String token = exchange.getRequest().getHeaders().getFirst(HttpHeaders.AUTHORIZATION);

//        if (!Auth0JwtUtils.verify(token)) {
//            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
//            return exchange.getResponse().setComplete();
//        }

        JSONObject jsonObject = new JSONObject(Auth0JwtUtils.getPayloadByBase64(token));
        Integer userId = jsonObject.getInt("userId");

        System.err.println("+++++++++++++++++++++userId="+userId);

        //异步调用feign，同步调用会出错！
        CompletableFuture<Integer> f = CompletableFuture.supplyAsync(()->{

            return userCenterOpenfeign.getCurrentUserId();
        });

        Integer currentUserId= null;
        try {
            currentUserId = f.get();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException(e);
        }

        //异步调用feign，同步调用会出错！
        CompletableFuture<Integer> f0 = CompletableFuture.supplyAsync(()->{

            return adminCenterOpenfeign.getCurrentAdminId();
        });

        Integer currentAdminId= null;
        try {
            currentAdminId = f0.get();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException(e);
        }

        if ( !userId.equals(currentUserId)&&!userId.equals(currentAdminId) ){
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }

        if(userId.equals(currentUserId)){
            //异步调用feign，同步调用会出错！
            CompletableFuture<String> f1 = CompletableFuture.supplyAsync(()->{

                return userCenterOpenfeign.getRefreshToken();
            });

            String refreshToken= null;
            try {
                refreshToken = f1.get();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException(e);
            } catch (ExecutionException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException(e);
            }

            if (LongAuth0JwtUtils.isExpired(refreshToken)){
                exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
                return exchange.getResponse().setComplete();
            }
            if (Auth0JwtUtils.isExpired(token)){
                Map<String,Object> map = new HashMap<>();
                map.put("userId",userId);
                String newToken = Auth0JwtUtils.sign(map);
                String newRefreshToken = LongAuth0JwtUtils.sign(map);
                //异步调用feign，同步调用会出错！
                CompletableFuture<String> f2 = CompletableFuture.supplyAsync(()->{
                    userCenterOpenfeign.setRefreshToken(newRefreshToken);
                    return "yes";
                });
                String yes= null;
                try {
                    yes = f2.get();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    throw new RuntimeException(e);
                } catch (ExecutionException e) {
                    Thread.currentThread().interrupt();
                    throw new RuntimeException(e);
                }
                // 将新令牌设置到响应头部
                exchange.getResponse().getHeaders().set("Authorization", newToken);
            }
        }
        if (userId.equals(currentAdminId)){
            //异步调用feign，同步调用会出错！
            CompletableFuture<String> f1 = CompletableFuture.supplyAsync(()->{

                return adminCenterOpenfeign.getRefreshToken();
            });

            String refreshToken= null;
            try {
                refreshToken = f1.get();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException(e);
            } catch (ExecutionException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException(e);
            }

            if (LongAuth0JwtUtils.isExpired(refreshToken)){
                exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
                return exchange.getResponse().setComplete();
            }
            if (Auth0JwtUtils.isExpired(token)){
                Map<String,Object> map = new HashMap<>();
                map.put("adminId",userId);
                String newToken = Auth0JwtUtils.sign(map);
                String newRefreshToken = LongAuth0JwtUtils.sign(map);
                //异步调用feign，同步调用会出错！
                CompletableFuture<String> f2 = CompletableFuture.supplyAsync(()->{
                    adminCenterOpenfeign.setRefreshToken(newRefreshToken);
                    return "yes";
                });
                String yes= null;
                try {
                    yes = f2.get();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    throw new RuntimeException(e);
                } catch (ExecutionException e) {
                    Thread.currentThread().interrupt();
                    throw new RuntimeException(e);
                }
                // 将新令牌设置到响应头部
                exchange.getResponse().getHeaders().set("Authorization", newToken);
            }
        }



        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }

    private boolean isWhiteList(String url) {
        for (String white : whiteList) {
            if (url.startsWith(white)) {
                return true;
            }
        }
        return false;
    }
}

